package xyz.xiezc.spider.downloader;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.setting.Setting;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import xyz.xiezc.ioc.annotation.Component;
import xyz.xiezc.ioc.annotation.InitMethod;
import xyz.xiezc.ioc.annotation.Inject;
import xyz.xiezc.spider.common.Request;
import xyz.xiezc.spider.common.XBean;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 下载器
 *
 * @author wb-xzc291800
 * @date 2019/04/03 9:22
 */
@Slf4j
@Component
public class DownloaderImpl implements Downloader {


    @Setter
    @Getter
    @Inject
    CookieManager cookieManager;

    private OkHttpClient client;

    @InitMethod
    public void init() {
        Dispatcher dispatcher = new Dispatcher();
        this.client = new OkHttpClient.Builder()
                .dispatcher(dispatcher)
                .cookieJar(cookieManager)
                .build();
    }

    @Override
    public  XBean downloader(XBean objectXBean) throws IOException {
        if (objectXBean == null) {
            return null;
        }
        Request request = objectXBean.getRequest();
        okhttp3.Request requestOk = createReq(request);
        Call call = client.newCall(requestOk);
        xyz.xiezc.spider.common.Response resp = getResp(call.execute());
        resp.setRequestId(request.getId());
        objectXBean.setResponse(resp);
        return objectXBean;
    }

    /**
     * 组装Request
     *
     * @param request
     * @return
     */
    private okhttp3.Request createReq(Request request) {
        Map<String, List<String>> header = request.getHeader();
        okhttp3.Request.Builder builder = new okhttp3.Request.Builder();
        //设置请求头
        Set<Map.Entry<String, List<String>>> entries = header.entrySet();
        for (Map.Entry<String, List<String>> entry : entries) {
            List<String> value = entry.getValue();
            for (String val : value) {
                builder.addHeader(entry.getKey(), val);
            }
        }

        log.info("download start, url:{}",request.getUrl());
        //设置url
        okhttp3.Request.Builder requestBuilder = builder.url(request.getUrl());
        String method = request.getMethod();

        //组装post请求
        if ("post".equalsIgnoreCase(method)) {
            xyz.xiezc.spider.common.RequestBody requestBody = request.getRequestBody();
            List<String> formData = requestBody.getFormData();
            xyz.xiezc.spider.common.MediaType mediaType = requestBody.getMediaType();
            //json
            if (mediaType.equals(xyz.xiezc.spider.common.MediaType.jsonContent)) {
                MediaType mediaTypeOk = MediaType.parse(xyz.xiezc.spider.common.MediaType.jsonContent.getContentType());
                RequestBody requestBody1 = FormBody.create(mediaTypeOk, formData.get(0));
                requestBuilder.post(requestBody1);
            }
            //form-data
            if (mediaType.equals(xyz.xiezc.spider.common.MediaType.formUrlencoded)) {
                FormBody.Builder builder1 = new FormBody.Builder();
                for (String str : formData) {
                    builder1.add(str.split("=")[0], str.split("=")[1]);
                }
                FormBody build = builder1.build();
                requestBuilder.post(build);
            }
            //multipart
            if (mediaType.equals(xyz.xiezc.spider.common.MediaType.multipart)) {
                MultipartBody.Builder builder2 = new MultipartBody.Builder();
                for (String str : formData) {
                    builder2.addFormDataPart(str.split("=")[0], str.split("=")[1]);
                }
                MultipartBody build = builder2.build();
                requestBuilder.post(build);
            }
        }
        //组装get请求
        if ("get".equalsIgnoreCase(method)) {
            requestBuilder.get();
        }
        return requestBuilder.build();
    }

    public xyz.xiezc.spider.common.Response getResp(Response response) {
        ResponseBody body = response.body();
        xyz.xiezc.spider.common.Response response1 = new xyz.xiezc.spider.common.Response();
        int code = response.code();
        response1.setCode(code);
        byte[] bytes = IoUtil.readBytes(body.byteStream());
        Charset charset = body.contentType().charset();
        response1.setCharset(charset);
        response1.setBodyByte(bytes);
        Headers headers = response.headers();
        Map<String, List<String>> stringListMap = headers.toMultimap();
        response1.setHeader(stringListMap);

        String s = body.contentType().toString();
        response1.setMediaType(xyz.xiezc.spider.common.MediaType.of(s));
        return response1;
    }

}
